home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Medal Software 3
/
Gold Medal Software - Volume 3 (Gold Medal) (1994).iso
/
wordproc
/
hshell1.arj
/
CPROG.HYP
/
cprog.HXP
Wrap
Text File
|
1993-12-29
|
16KB
|
873 lines
/*
.REMARK
Example C program source file set up as a hyperfile
The C Program is in the public domain
WARNING: - Program is from Unix system and will need
modification to compile and run on MSDOS
- The program must not be edited using HE
- SETUP script must not be longer than 199 lines
.HEADER
~DRFile: $3 Function: $1 [$2]~DT
.FOOTER
[d] ~NDeclarations~PA@MDeclarations~Kd~E [ ] ~A-- Press space to continue --~Pk# ~K ~E [r] ~A"Return"~PB~Kr~E
.SCRIPT SETUP
K# F+
O43
ZANBraces:NGlobals A
ZANLineNumber:NGlobals A
ZANPageNumber:NGlobals A
ZANPageLength:NGlobals A
ZANPagePart:NGlobals A
ZANPageEnd:NGlobals A
ZANSawFunction:NGlobals A
ZANInComment:NGlobals A
ZANInString:NGlobals A
ZANFileLineNumber:NGlobals A
ZANProgName:NGlobals A
ZANToday:NGlobals A
ZANCurrentName:NGlobals A
ZANFunctionName:NGlobals B
ZANFileDate:NGlobals B
ZANSortFlag:NGlobals B
ZANNumberFlag:NGlobals B
ZANSpace_to_leave:NGlobals B
ZANTabWidth:NGlobals B
ZANToc:NGlobals B
ZANTocPages:NGlobals B
ZANTocCount:NGlobals B
ZANSaveOut:NGlobals B
ZANTempName:NGlobals B
ZANTemp2Name:NGlobals B
ZANBP:NDefines
ZANTOC_SIZE:NDefines
ZANNEWFILE:NDefines
ZANNEWFUNCTION:NDefines
ZANisidchr:NDefines
.
.MENU Declarations
Includes|NIncludes
Defines|NDefines
Externals|NExternals
Globals A|NGlobals A
Globals B|NGlobals B
.
*/
/*
.NOTE Includes
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include <string.h>
/*
.NOTE Defines
*/
#define BP 0xC /* Form feed */
#define TOC_SIZE 4096
#define NEWFILE 1
#define NEWFUNCTION 2
#define isidchr(c) (isalnum(c) || (c == '_'))
/*
.NOTE Externals
*/
extern int errno; /* system error number */
extern char *sys_errlist[]; /* error message */
/*
.NOTE Globals A
*/
FILE *File;
int Braces; /* Keeps track of brace depth */
int LineNumber; /* Count output lines */
int PageNumber = 0; /* You figure this one out */
int PageLength = 66; /* -l <len> Normal paper length */
int PagePart = 12; /* Decision on paging for new fn*/
int PageEnd; /* Accounts for space at bottom */
int SawFunction;
int InComment;
int InString;
long FileLineNumber; /* Input file line number */
char *ProgName;
char Today[30];
char *CurrentName; /* Current file name */
/*
.NOTE Globals B
*/
char FunctionName[80];
char FileDate[24]; /* Last modified time of file */
char SortFlag; /* -s == sort table of contents */
char NumberFlag; /* -n == output line numbers */
int Space_to_leave = 5; /* -r<number> space to leave */
int TabWidth = 0; /* -t <number> width of tabs */
char *Toc[TOC_SIZE];
int TocPages[TOC_SIZE];
int TocCount;
int SaveOut;
char *TempName;
char *Temp2Name;
/*
.FRAME Introduction
* This program prints the files named in its argument list, preceding
* the output with a table of contents. Each file is assumed to be C
* source code (but doesn't have to be) in that the program searches
* for the beginning and end of functions. Function names are added to
* the table of contents, provided the name starts at the beginning of
* a line. The function name in the output is double striken.
*
* By default blank space is inserted after every closing '}'
* character. Thus functions and structure declarations are nicely
* isolated in the output. The only drawback to this is that structure
* initialization tables sometimes produce lots of white space.
* The "-r" option removes this space, or changes it to the indicated
* length.
*
* The option "-l" indicates that the following argument is to be
* the page length used for output (changing the page length hasn't been
* tested much).
*
* The option "-s" indicates that the table of contents should be sorted
* by function name within each file.
*
* The option "-n" indicates that output lines should be numbered with
* the corresponding line number from the input file.
*
* The option "-p" indicates what proportion of the page in steps of 16
* should be used for deciding if a new function needs a new page.
* That is -p12 (the default) indicates that if a function starts
* within the top 12/16 (3/4) of the page then do it, otherwise put it
* on a new page. Thus the higher the number (upto 16) the closer to
* the bottom of the page will functions be started. -p0 says put each
* func on a new page.
*
* Written by:
* Paul Breslin
* Human Computing Resources Corp.
* 10 St. Mary St.
* Toronto, Ontario
* Canada, M4Y 1P9
*
* Careful:
* It will find things like struct foo *f()...
* but not things like int
* f
* ()...
* ie. the constraint is that the () must appear on the same line
* as the function name.
*/
/*
.FRAME main
.TITLE Control function
*/
main(argc, argv)
char **argv;
{
register int i;
char *ctime();
time_t thetime, time();
char *parm;
int c;
ProgName = argv[0];
thetime = time((time_t *)0);
strcpy(Today,ctime(&thetime));
for( i=1; argc > i; ++i )
{
if( argv[i][0] != '-'
|| argv[i][1] == '\0' ) break;
parm = argv[i];
while( c = *++parm ) switch( c ){
case 't':
if( argc < 3 ) Usage();
TabWidth = atoi(argv[++i]);
if( TabWidth < 0 )
TabWidth = 0;
break;
case 'l':
if( argc < 3 ) Usage();
PageLength = atoi(argv[++i]);
break;
case 's':
++SortFlag;
break;
case 'n':
++NumberFlag;
break;
case 'r':
if( (c = parm[1]) && isdigit( c )
&&( c = atoi( parm+1 )) > 0 ){
Space_to_leave = c;
} else {
Space_to_leave = 0;
}
while( *parm ){
++parm;
}
--parm;
break;
case 'p':
if( (c = parm[1]) && isdigit( c )
&&( c = atoi( parm+1 )) >= 0 ){
PagePart = (c <= 16) ? c: 16;
}
while( *parm ){
++parm;
}
--parm;
break;
default:
Usage();
break;
}
}
PageEnd = PageLength - ((PageLength > 30) ? 2 : 1);
StartTempFile();
if( i == argc )
{ /* no file names */
File = stdin;
CurrentName = "Standard Input";
List();
}
for(; i < argc; ++i )
{
if( strcmp(argv[i], "-") == 0 )
{
File = stdin;
CurrentName = "Standard Input";
}
else
{
if( (File = fopen( CurrentName = argv[i], "r" )) == NULL )
{
fprintf(stderr,"%s: Can't open file '%s': %s\n",
ProgName, CurrentName, sys_errlist[errno] );
continue;
}
}
List();
if( File != stdin ) fclose(File);
}
if( PageNumber > 1 || LineNumber > 0 )
putchar(BP);
EndTempFile();
DumpTableOfContents();
DumpTempFiles();
Done();
}
/*
.FRAME Usage
.TITLE Print program usage
*/
Usage()
{
fprintf(stderr, "Usage: %s [-n] [-t tabwidth] [-p[num]] [-r[num]] [-s] [-l pagelength] [files] [-]\n",
ProgName);
exit(1);
}
/*
.FRAME StartTempFile
.TITLE Open temporary file
*/
StartTempFile()
{
int Done();
extern char *mktemp();
CatchSignalsPlease(Done);
SaveOut = dup(1);
TempName = mktemp("/tmp/cprXXXXXX");
if( freopen(TempName, "w", stdout) == NULL )
{
fprintf(stderr, "%s: Can't open temp file '%s': %s\n", ProgName,
TempName, sys_errlist[errno]);
exit(1);
}
}
/*
.FRAME EndTempFile
.TITLE Handle temporary file
*/
EndTempFile()
{
Temp2Name = mktemp("/tmp/CPRXXXXXX");
if( freopen(Temp2Name, "w", stdout) == NULL )
{
fprintf(stderr, "%s: Can't open temp file '%s': %s\n", ProgName,
Temp2Name, sys_errlist[errno]);
exit(1);
}
}
/*
.FRAME DumpTempFiles
.TITLE Output from temporary area
*/
DumpTempFiles()
{
register int pid, w;
fclose(stdout);
dup(SaveOut);
while( (pid = fork()) < 0 ) sleep(1);
if( pid )
while ((w = wait(0)) != pid && w != -1);
else
{
CatchSignalsPlease(SIG_DFL);
execl( "/bin/cat", "cat", Temp2Name, TempName, 0 );
fprintf(stderr, "%s: exec of /bin/cat failed: %s\n", ProgName,
sys_errlist[errno]);
exit(0);
}
}
/*
.FRAME Done
.TITLE Finished
*/
Done()
{
CatchSignalsPlease(SIG_IGN);
if( TempName ) unlink( TempName );
if( Temp2Name ) unlink( Temp2Name );
exit(0);
}
/*
.FRAME CatchSignalsPlease
.TITLE Signal handler
*/
CatchSignalsPlease(action)
int (*action)();
{
if( signal(SIGINT, SIG_IGN) != SIG_IGN ) signal(SIGINT, action);
if( signal(SIGQUIT, SIG_IGN) != SIG_IGN ) signal(SIGQUIT, action);
if( signal(SIGHUP, SIG_IGN) != SIG_IGN ) signal(SIGHUP, action);
}
/*
.FRAME List
.TITLE Produce list
*/
List()
{
register int bp;
register char *bufp;
char buffer[256];
NewFile();
bp = Braces = 0;
InString = InComment = 0; /* reset for new file -DV */
SawFunction = 0;
bufp = buffer;
while( fgets(bufp, sizeof(buffer), File) != NULL )
{
++FileLineNumber;
if( bp ) NewFunction();
if( ++LineNumber >= PageEnd ) NewPage();
if( bufp[0] == '\f'
&& bufp[1] == '\n'
&& bufp[2] == '\0' ) NewPage(); /* was strcpy(bufp, "^L\n");*/
if( NumberFlag )
{
if( *bufp == '\n' )
printf(" ");
else
printf("%6ld ", FileLineNumber);
}
if( (Braces == 0) && LooksLikeFunction(bufp) )
AddToTableOfContents(NEWFUNCTION);
bp = PutLine(buffer);
}
}
/*
.FRAME PutLine
.TITLE Output line
*/
PutLine(l)
register char *l;
{
extern char *EndComment();
extern char *EndString();
register char c;
int bp;
char *save;
bp = 0;
for( save = l; c = *l; ++l )
if( InComment )
l = EndComment(l);
else if( InString )
l = EndString(l);
else
switch(c)
{
case '{':
++Braces;
break;
case '}':
if( --Braces == 0 )
bp = 1;
break;
case '\'':
for( ++l; *l && *l != '\''; ++l )
if( *l == '\\' && *(l+1) ) ++l;
break;
case '"':
InString = 1;
break;
case '/':
if( *(l+1) == '*' )
{
InComment = 1;
++l;
}
break;
}
printf("%s", save);
return(bp);
}
/*
.FRAME EndComment
.TITLE End of comment
*/
char *
EndComment(p)
register char *p;
{
register char c;
/*
* Always return pointer to last non-null char looked at.
*/
while( c = *p++ )
if( c == '*' && *p == '/' )
{
InComment = 0;
return(p);
}
return(p-2);
}
/*
.FRAME EndString
.TITLE End of string
*/
char *
EndString(p)
register char *p;
{
register char c;
/*
* Always return pointer to last non-null char looked at.
*/
while( c = *p++ )
if( c == '\\' && *p )
{
++p;
continue;
}
else if( c == '"' )
{
InString = 0;
return(p-1);
}
return(p-2);
}
/*
.FRAME NewFunction
.TITLE Process new function
*/
NewFunction()
{
register int i;
if( Space_to_leave <= 0 || !SawFunction ) return;
if( LineNumber + Space_to_leave > (PageLength * PagePart / 16) )
NewPage();
else
{
for( i=0; i < (Space_to_leave); ++i ) putchar('\n');
LineNumber += Space_to_leave;
}
SawFunction = 0;
}
#define HEADER_SIZE 3
/*
.FRAME NewPage
.TITLE Start new page
*/
NewPage()
{
if( PageNumber >= 0 ) ++PageNumber;
putchar(BP);
LineNumber = 0;
PutHeader();
}
/*
.FRAME PutHeader
.TITLE Output header
*/
PutHeader()
{
register int i, l, j;
putchar('\n');
++LineNumber;
l = strlen(CurrentName);
for( j=0; j < l; ++j )
printf("%c\b%c\b%c", CurrentName[j], CurrentName[j], CurrentName[j]);
if( PageNumber > 0 )
{
printf(" %.17s", FileDate);
GoToColumn(l+19, 70);
printf("Page:%4d\n\n", PageNumber);
++LineNumber;
++LineNumber;
}
else
{
GoToColumn(l, 55);
printf("%s\n\n", Today);
++LineNumber;
++LineNumber;
}
}
/*
.FRAME GoToColumn
.TITLE Tabulate
*/
GoToColumn(from, to)
register int from, to;
{
if( from < to)
{
if( TabWidth > 0 ){
from &= ~(TabWidth-1);
for( ; (from + TabWidth) <= to; from += TabWidth )
putchar('\t');
}
for( ; from < to; from++ )
putchar(' ');
}
}
/*
.FRAME LooksLikeFunction
.TITLE Function definition
*/
LooksLikeFunction(s)
register char *s;
{
register char *p;
register int i;
char *save;
if( InComment || InString ) return(0);
save = s;
i = 0;
do
{
p = FunctionName;
if( *s == '*' ) ++s;
if( (*s != '_') && !isalpha(*s) ) return(0);
while( isidchr(*s) )
*p++ = *s++;
*p = '\0';
while( (*s == ' ') || (*s == '\t') ) ++s;
i++;
}
while ( *s && *s != '(' && i < 4 );
if( *s != '(' || *(s+1) == '*' ) return(0);
for (i = 0; *s; s++)
{
switch( *s )
{
case '(':
++i;
continue;
case ')':
--i;
break;
default:
break;
}
if( i == 0 ) break;
}
if( !*s ) return(0);
while( *s )
{
if( *s == '{') break;
if( *s == ';' || *s == ':' ) return(0);
++s;
}
/*
* This will cause the function name part of the line to
* be double striken. Note that this assumes the name and the opening
* parentheses are on the same line...
*/
if( p = strchr( save, '(' ) )
{
p--;
while( p != save && isidchr( *(p-1) ) ) p--;
for( i=0; save != p; save++, i++ ) putchar(' ');
for( ; *p != '('; p++, i++ ) putchar( *p );
}
else
for( i=0; *save && (*save == '*' || isidchr(*save)); ++i, ++save)
if( *save == '*' )
putchar(' ');
else
putchar(*save);
while( i --> 0 ) putchar('\b');
SawFunction = 1;
return(1);
}
/*
.FRAME AddToTableOfContents
.TITLE Add To Table Of Contents
*/
AddToTableOfContents(type)
{
if( TocCount > TOC_SIZE )
return;
if( TocCount == TOC_SIZE )
{
fprintf(stderr, "%s: More than %d Table of contents entries; others ignored.\n",
ProgName, TOC_SIZE);
++TocCount;
return;
}
if( type == NEWFILE )
AddFile();
else
AddFunction();
}
/*
.FRAME AddFunction
.TITLE Add function to table of contents
*/
AddFunction()
{
register int l;
register char *p;
/* This heuristic stops multiple occurrences of a function,
* selected by #ifdefs, to all end up many times over in the
* Table of Contents. One only needs to see it once. -IAN!
*/
if( TocCount > 0 && TocPages[TocCount-1] == PageNumber
&& strcmp(Toc[TocCount-1],FunctionName) == 0 )
return;
l = strlen(FunctionName);
p = Toc[TocCount] = (char *)malloc(l+1);
strcpy(p, FunctionName);
TocPages[TocCount] = PageNumber;
++TocCount;
}
/*
.FRAME AddFile
.TITLE Add file to table of contents
*/
AddFile()
{
register int i, l;
register int len;
char temp[20];
len = strlen(CurrentName) + 20;
len = (len < 130) ? 130 : len;
Toc[TocCount] = (char *)malloc(len);
sprintf(Toc[TocCount], "\n File: %s ", CurrentName);
l = strlen(Toc[TocCount]);
if( l < 64 )
{
if( TabWidth > 0 ){
i = ((64 - l) / TabWidth) + 1;
while( i-- > 0 )
Toc[TocCount][l++] = '\t';
}
else{
while( l < 64 )
Toc[TocCount][l++] = ' ';
}
Toc[TocCount][l++] = '\0';
}
sprintf(temp, " Page %4d\n", PageNumber);
strcat(Toc[TocCount], temp);
++TocCount;
}
/*
.FRAME NewFile
.TITLE Start next file
*/
NewFile()
{
GetFileTime();
NewPage();
AddToTableOfContents(NEWFILE);
FileLineNumber = 0;
}
/*
.FRAME GetFileTime
.TITLE Get the file modification time
*/
GetFileTime()
{
struct stat st;
if( File == stdin )
strncpy(FileDate, &Today[4], 20);
else
{
fstat(fileno(File), &st);
strncpy(FileDate, ctime(&st.st_mtime) + 4, 20);
}
strncpy(&FileDate[12], &FileDate[15], 5);
FileDate[18] = '\0';
}
/*
.FRAME DumpTableOfContents
.TITLE Outputs table of contents
*/
DumpTableOfContents()
{
register int i, j;
int index[TOC_SIZE];
if( TocCount == 0 ) return;
for (i = 0; i < TocCount; i++) index[i] = i;
if( SortFlag )
SortTable(index);
CurrentName = "Table of Contents";
PageNumber = -1;
LineNumber = 0;
NewPage();
for( i=0; i < TocCount; ++i )
{
if( Toc[index[i]][0] == '\n' )
{
if( (LineNumber + 5) >= PageEnd ) NewPage();
printf("%s", Toc[index[i]]);
LineNumber += 2;
continue;
}
if( ++LineNumber >= PageEnd ) NewPage();
printf(" %s ", Toc[index[i]]);
for( j=strlen(Toc[index[i]]); j < 48; ++j ) putchar('.');
printf(" %4d\n", TocPages[index[i]]);
}
}
/*
.FRAME SortTable
.TITLE Sorts table of contents
*/
SortTable(index)
register int *index;
{
register int i, temp, flag;
do {
flag = 0;
for (i = 0; i < TocCount - 1; i++)
{
if( Toc[index[i]][0] == '\n' || Toc[index[i+1]][0] == '\n' )
continue; /* don't sort across file names */
if( strcmp(Toc[index[i]], Toc[index[i+1]]) > 0)
{
temp = index[i];
index[i] = index[i+1];
index[i+1] = temp;
flag = 1;
}
}
} while( flag );
}
/*
.REMARK
END OF SOURCE PROGRAM
*/